package com.wjf.birdfish.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.log4j.Logger;

/**
 * 
 *<p>
 * Title:ZIP文件处理
 *</p>
 * <p>
 * Description:ZIP文件处理
 * </p>
 * 
 * @version
 * @author liangzhangping
 * @date 2012-3-21
 * @since
 * 
 */
public class ZipFileUtil {
	private static Logger LOG = Logger.getLogger(ZipFileUtil.class.getName());
	private static final int BUFFER_SIZE = 4096;

	/**
	 * 将文件或目录压缩成ZIP包
	 * 
	 * @param src
	 *            源文件或目录
	 * @param dest
	 *            ZIP文件路径
	 * @return boolean 成功返回true，失败为false
	 * @throws Exception
	 */
	public static boolean zip(String src, String dest) {
		if (src == null || dest == null) {
			LOG.error("zip:src=" + src + ", dest=" + dest);
			throw new IllegalArgumentException("src or dest is null");
		}
		File destFile = null;
		try {
			destFile = FileUtil.createPathAndFile(dest);
		} catch (IOException e) {
			LOG.error("create  destFile error",e);
			return false;
		}
		File srcFile = null;
		try {
			srcFile = FileUtil.createPath(src);
		} catch (IOException e) {
			LOG.error("create  srcFile error",e);
			return false;
		}
		
		OutputStream os = null;
		try {
			os = new BufferedOutputStream(new FileOutputStream(destFile, false));
		} catch (FileNotFoundException e1) {
			LOG.error("dest get OutputStream error",e1);
			return false;
		}
		ZipArchiveOutputStream zos = new ZipArchiveOutputStream(os);
		zos.setEncoding(Charset.defaultCharset().name());
		byte[] buffer = new byte[BUFFER_SIZE];
		try {
			zipRecursive(srcFile, "", zos, buffer);
			return true;
		} catch (Exception e) {
			LOG.error("zip error:src=" + src + ",dest=" + dest, e);
			return false;
		} finally {
			if (zos != null) {
				try {
					zos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private static void zipRecursive(File dir, String base,
			ZipArchiveOutputStream zos, byte[] buffer) throws IOException {
		ZipArchiveEntry entry;

		if (dir.isFile()) {
			if (base.length() == 0) {
				base = dir.getName();
			}
			entry = new ZipArchiveEntry(base);
			zos.putArchiveEntry(entry);
			InputStream is = new BufferedInputStream(new FileInputStream(dir));
			int count;
			try {
				while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) {
					zos.write(buffer, 0, count);
				}
				zos.closeArchiveEntry();
			} finally {
				if (is != null) {
					is.close();
				}
			}
		} else {
			if (base.length() > 0) {
				base = base + "/";
			}
			entry = new ZipArchiveEntry(base);
			zos.putArchiveEntry(entry);
			File[] currents = dir.listFiles();
			if (currents != null) {
				for (File current : currents) {
					zipRecursive(current, base + current.getName(), zos, buffer);
				}
			}
		}
	}

	/**
	 * 将ZIP包解压缩到指定路径
	 * 
	 * @param srcFile
	 *            ZIP文件路径
	 * @param dest
	 *            目标目录路径
	 * @return boolean 成功返回true，失败为false
	 */
	public static boolean unzip(String srcPath, String destPath) {
		if (srcPath == null || destPath == null) {
			LOG.error("unzip:src=" + srcPath + ", destDir=" + destPath);
			throw new IllegalArgumentException("srcPath or destPath is null");
		}
		File src = new File(srcPath);
		File dest = null;
		try {
			dest = FileUtil.createPath(destPath);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return unzip(src, dest);
	}
	public static boolean unzip(File src, File dest) {
		if (src == null || dest == null) {
			LOG.error("unzip:src=" + src + ", destDir=" + dest);
			throw new IllegalArgumentException("src or dest is null");
		}
		ZipArchiveInputStream zis = null;
		try {
			InputStream in = new BufferedInputStream(new FileInputStream(src));
			zis = new ZipArchiveInputStream(in, null, true);

			if (!dest.exists()) {
				dest.mkdir();
			}
			byte[] buffer = new byte[BUFFER_SIZE];
			String filename;
			ZipArchiveEntry entry;
			int count;
			String destDir = dest.getAbsolutePath();
			while ((entry = zis.getNextZipEntry()) != null) {
				String entryName = entry.getName();
				if (entryName.length() == 0) {
					continue;
				}
				filename = destDir + "/" + entryName;
				File tmpDest = new File(filename);
				if (entry.isDirectory()) {
					tmpDest.mkdir();
				} else {
					OutputStream destStream = new BufferedOutputStream(
							new FileOutputStream(tmpDest, false));
					try {
						while ((count = zis.read(buffer, 0, BUFFER_SIZE)) != -1) {
							destStream.write(buffer, 0, count);
						}
					} finally {
						if (destStream != null) {
							destStream.close();
						}
					}
				}
			}
			return true;
		} catch (Exception e) {
			LOG.error("unzip error:zipfile=" + src + ",destPath=" + dest, e);
			return false;
		} finally {
			if (zis != null) {
				try {
					zis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 列举ZIP包的内容
	 * 
	 * @param file
	 *            ZIP文件路径
	 * @param recursive
	 *            true:递归读取根目录及子目录，false：只读取根目录
	 * @return List<ZipEntry> ZIP包的内容
	 */
	public static List<ZipArchiveEntry> listZipFile(File src, boolean recursive) {
		if (src == null) {
			LOG.error("listZipFile:src=" + src);
			throw new IllegalArgumentException("src is null");
		}
		List<ZipArchiveEntry> items = new ArrayList<ZipArchiveEntry>();
		ZipArchiveInputStream zis = null;
		try {
			zis = new ZipArchiveInputStream(new BufferedInputStream(
					new FileInputStream(src)), null, true);
			ZipArchiveEntry entry;
			String entryName;
			if (recursive) {
				while ((entry = zis.getNextZipEntry()) != null) {
					entryName = entry.getName();
					if (!entry.isDirectory() && !entryName.isEmpty()) {
						items.add(entry);
					}
				}
			} else {
				while ((entry = zis.getNextZipEntry()) != null) {
					entryName = entry.getName();
					if (!entry.isDirectory() && !entryName.isEmpty()
							&& entryName.indexOf('/') == -1) {
						items.add(entry);
					}
				}
			}
		} catch (IOException e) {
			LOG.error("listZipFile error:zipfile=" + src + ",recursive="
					+ recursive, e);
		} finally {
			if (zis != null) {
				try {
					zis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return items;
	}
	
	public static void main(String[] args){
		//unzip("C:\\Users\\lzp\\Desktop\\lzp\\AccpHisSer.zip","C:\\Users\\lzp\\Desktop\\lzp\\Test\\1\\2\\3");
		try {
			zip("C:\\Users\\lzp\\Desktop\\lzp\\Test\\1\\2\\3\\AccpHisSer","C:\\Users\\lzp\\Desktop\\lzp\\Test\\1\\2\\3\\4\\5\\AccpHisSer.zip");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
